<template>
  <onez-view viewid="scene" class="sceneBox" :style="{ transform: 'scale3d(' + sceneZoom + ',' + sceneZoom + ',' + sceneZoom + ')' }">
    <onez-node ref="sceneBack" class="onez-scene onez-scene-back" :info="infoBack" v-if="infoBack"></onez-node>
    <onez-node ref="scene" class="onez-scene onez-scene-front" :winSize="winSize" :info="info" v-if="info" @hit="hit">
      <onez-view class="tiles" v-if="tiles">
        <onez-view
          v-for="(tile, key) in tiles"
          class="tile"
          :style="{ left: tile.c * tilesize + 'px', top: tile.r * tilesize + 'px', backgroundImage: tile.show ? 'url(' + tileurl + '/' + tile.c + ',' + tile.r + '.png)' : 'none' }"
        ></onez-view>
      </onez-view>
      <template v-if="showGoods">
        <onez-role :ref="'role-' + id" :roleId="id" v-for="(id, index) in roles" :key="index" @move="roleMove" @ready="roleReady"></onez-role>
        <onez-role class="npc" v-if="npc.length" v-for="(item, index) in npc" @ready="roleReady" @click="onNpc" :ref="'role-' + item._id" :item="item" type="npc"></onez-role>
      </template>
      <template v-if="goods.length" v-for="(item, index2) in goods">
        <onez-node class="goods" :ref="'goods-' + item.id" :info="item"></onez-node>
      </template>

      <onez-node ref="mouse" v-show="mouse_show" resid="A64EE238-6329-EA77-D60F-EBAB152D7D2C" :play="false"></onez-node>
      <slot :scene="info"></slot>
    </onez-node>
    <onez-view
      v-if="smallMap && smallMap.show"
      class="smallMap"
      :style="{
        left: smallMap.left + 'px',
        top: smallMap.top + 'px',
        width: smallMap.width + 'px',
        height: smallMap.height + 'px',
        backgroundImage: 'url(' + smallMap.pic + ')'
      }"
    >
      <onez-node class="dot" :style="{ left: smallMap.x + 'px', top: smallMap.y + 'px' }" resid="51D73031-80D9-F86D-0100-0AFE7F30FC05#main/image_numbg.png"></onez-node>
      <onez-background
        @click.native="smallMap.show = false"
        class="border"
        resid="8254B0B7-C1E8-F929-C164-BA8C94638490"
        :style="{
          width: smallMap.width + 10 + 'px',
          height: smallMap.height + 10 + 'px'
        }"
        :size="smallMap.width + ',' + smallMap.height"
      ></onez-background>
    </onez-view>
  </onez-view>
</template>
<script>
	import onezView from '../onez-view/onez-view.vue'
	import onezNode from '../onez-node/onez-node.vue'
	import onezRole from '../onez-role/onez-role.vue'
	import onezBackground from '../onez-background/onez-background.vue'
export default {
  name: 'onez-scene',
  components: {
  	onezView, onezRole, onezNode, onezBackground
  },
  props: {
    scene: {
      type: String,
      default: 'auto'
    }
  },
  data() {
    return {
      showGoods: true,
      mouse_show: false,
      smallMap: null,
      infoBack: null,
      winSize: null,
      info: null,
      tileurl: null,
      tiles: null,
      music: null,
      transform: null,
      map_arr: [],
      paths: [],
      ways: [],
      npc: [],
      goods: [],
      size: 32,
      width: 0,
      height: 0,
      col: 0,
      row: 0,
      tileR: 0,
      zoom: 1,
      sceneZoom: 1,
      roles: []
    };
  },
  watch: {
    scene(nVal, oVal) {
      this.init();
    }
  },
  mounted() {
    this.init();
    this.$game.$on('global-update', this.onGlobalUpdate);
    this.$game.$on('game-event', this.onGameEvent);
  },
  beforeDestroy() {
    if (this.socket) {
      this.$game.socket_scene = null;
      this.socket.disconnect();
    }
    this.$game.$off('global-update', this.onGlobalUpdate);
    this.$game.$off('game-event', this.onGameEvent);
  },
  methods: {
    onGlobalUpdate(e) {},
    onGameEvent(e) {
      if (e.type == 'showMap') {
        this.smallMap.width = this.info.width * this.smallMap.zoom;
        this.smallMap.height = this.info.height * this.smallMap.zoom;
        this.smallMap.left = (this.$game.width - this.smallMap.width) / 2;
        this.smallMap.top = (this.$game.height - this.smallMap.height) / 2;
        this.smallMap.show = true;
      }
    },
    async onNpc(item) {
      await this.$game.hook(this, 'prop', { type: 'npc', item: item });
    },
    async init() {
      var that = this;

      let info = await this.$game.hook(this, 'scene_before');
      if (!info) {
        info = await this.$game.hook(this, 'scene', { sceneName: this.scene });
      }
      if (!info || !info.pic) {
        return this.$game.error('加载场景失败');
      }
      info.is_scene = true;
      if (info.pic_back) {
        var infoBack = JSON.parse(JSON.stringify(info));
        infoBack.pic = info.pic_back;
        infoBack = infoBack;
      }

      this.tileurl = info.pic.split('.png')[0];
      this.zoom = info.zoom || 1;
      this.size = 32 * this.zoom;
      this.col = Math.floor(info.width / this.size);
      this.row = Math.floor(info.height / this.size);
      this.tilesize = 320 * this.zoom;
      this.tileR = Math.ceil(info.width / this.tilesize);
      this.tileB = Math.ceil(info.height / this.tilesize);
      if (info.music) {
        if (info.music.length == 36 && info.music.indexOf('http') == -1) {
          let r = await this.$game.hook(this, 'res', { resid: info.music });
          info.music = r.url;
        }
        this.$game.playMusic(info.music);
      }
      //尺寸超过2000启用切片
      if (info.width > 2000) {
        let tiles = {};
        info.pic += '!mobi';
        for (let r = 0; r <= this.tileB; r++) {
          for (let c = 0; c <= this.tileR; c++) {
            tiles[c + ',' + r] = {
              c: c,
              r: r,
              show: false
            };
          }
        }
        this.tiles = tiles;
      }
      let smallMap = { show: false };
      let bl = 0.7;
      let zoom = Math.min((this.$game.width * bl) / info.width, (this.$game.height * bl) / info.height);
      smallMap.width = info.width * zoom;
      smallMap.height = info.height * zoom;
      smallMap.left = (this.$game.width - smallMap.width) / 2;
      smallMap.top = (this.$game.height - smallMap.height) / 2;
      smallMap.pic = info.pic;
      smallMap.x = 0;
      smallMap.y = 0;
      smallMap.zoom = zoom;
      this.smallMap = smallMap;

      this.sceneUpdate();

      this.$game.onResize(this.resize);
      this.map_arr = [];
      for (var x = 0; x < this.col; x++) {
        var arrY = [];
        for (var y = 0; y < this.row; y++) {
          if (info.path == null || info.path == '') {
            arrY.push(1);
          } else {
            arrY.push(info.path.indexOf('|' + x + ',' + y + '|') == -1 ? 0 : 1);
          }
          if (arrY[arrY.length - 1] == 1) {
            this.paths.push([x, y]);
          }
        }
        this.map_arr.push(arrY);
      }
      var that = this;
      if (this.socket) {
        this.socket.disconnect();
      }
      if (info.websocket && info.websocket.room) {
        var socket = this.$game.io.connect(
          info.websocket.host,
          { forceNew: true }
        );
        socket.on('getmsg', item => {
          that.getMsg(item);
        });
        socket.on('welcome', item => {
          console.log(that.$game.uid());
          var option = { uid: that.$game.uid(), room: info.websocket.room, apiurl: that.$game.apiurl, app: 'game', info: info.websocket.roominfo };
          if (info.plugin) {
            option.plugin = info.plugin;
          }
          socket.emit('join', option);
          socket.emit('getRoomList', {});
        });
        socket.on('roomlist', item => {
          that.listUpdate(item);
        });
        this.socket = socket;
        this.$game.socket_scene = socket;
      }
      this.roles.push(this.$game.uid());
      this.info = info;
      console.log('~~~~~~~~',info);
      this.$emit('ready', this);
      await this.$game.hook(this, 'scene_after', info);
    },
    async sceneUpdate() {
      let npc = [];
      let goods = [];
      let info = await this.$game.hook(this, 'scene', { sceneName: this.scene });
      //加载NPC
      if (info.npc) {
        info.npc.forEach(item => {
          item.event = {
            action: 'prop',
            type: 'npc',
            item: item
          };
          npc.push(item);
        });
      }
      //加载物品
      if (info.goods) {
        info.goods.forEach(item => {
          let pos = this.$game.formatPos(item.mypos);
          item.x = pos[0] * this.size;
          item.y = pos[1] * this.size;
          item.event = {
            action: 'prop',
            type: 'goods',
            item: item
          };
          goods.push(item);
        });
      }
      this.showGoods = false;
      await this.$game.wait(this);
      this.npc = npc;
      this.goods = goods;
      this.showGoods = true;
      this.$forceUpdate();
    },
    getMsg(msg) {
      console.log('~~~~~~~~~~~~~~~~~~~~~~,getMsg', msg);
      this.$emit('getmsg', msg);
      if (msg.type == 'in' || msg.type == 'out') {
        this.socket.emit('getRoomList', {});
      } else if (msg.type == 'scene-update') {
        this.sceneUpdate();
      } else if (msg.type == 'wayTo') {
        this.role(msg.roleId, role => {
          role.wayTo(this, msg.paths);
        });
      }
    },
    //自动加载大图，切片
    updateBigMap(left, top) {
      let tileBeginX = Math.floor(left / this.tilesize);
      let tileBeginY = Math.floor(top / this.tilesize);
      let tileEndX = Math.floor((left + this.$game.width) / this.tilesize);
      let tileEndY = Math.floor((top + this.$game.height) / this.tilesize);
      if (tileBeginX < 0) {
        tileBeginX = 0;
      }
      if (tileBeginY < 0) {
        tileBeginY = 0;
      }
      if (tileEndX > this.tileR) {
        tileEndX = this.tileR;
      }
      if (tileEndY > this.tileB) {
        tileEndY = this.tileB;
      }
      for (let r = tileBeginY; r <= tileEndY; r++) {
        for (let c = tileBeginX; c <= tileEndX; c++) {
          if (this.tiles && this.tiles[c + ',' + r] && !this.tiles[c + ',' + r].show) {
            this.tiles[c + ',' + r].show = true;
          }
        }
      }
    },
    listUpdate(item) {
      console.log('~~~~~~~~~~~~~~~~~~~~~~,listUpdate', item.uids);
      if (!item.uids) {
        return;
      }
      var roles = [];
      for (var i = 0; i < item.uids.length; i++) {
        var uid = item.uids[i];
        if (roles.indexOf(uid) == -1) {
          roles.push(uid);
        }
      }
      this.roles = roles;
    },
    async resize(e) {
      let systemInfo = await this.$game.getSystemInfoSync();
      this.width = systemInfo.windowWidth;
      this.height = systemInfo.windowHeight;
      this.$game.width = this.width;
      this.$game.height = this.height;
      if (this.infoBack) {
        this.sceneZoom = Math.max(this.height / this.info.height, this.width / this.info.width);
      }
      this.roleMove({ roleId: this.$game.uid(), animate: 0 });
      this.winSize={
        width:this.width,
        height:this.height,
        sceneZoom:this.sceneZoom,
      };
    },
    role(id, callback) {
      this.$nextTick(() => {
        var role = this.$refs['role-' + id];
        if (role) {
          callback(role[0]);
        }
      });
    },
    getRole(id) {
      return new Promise((resolve, reject) => {
        if (this.$refs['role-' + id]) {
          resolve(this.$refs['role-' + id][0]);
        } else {
          this.$nextTick(() => {
            var role = this.$refs['role-' + id];
            if (role) {
              resolve(role[0]);
            } else {
              resolve(false);
            }
          });
        }
      });
    },
    async roleReady(roleId) {
      if (!this.info.path) {
        return;
      }
      var role = await this.getRole(roleId);
      if (!role) {
        return;
      }
      var mypos = '|' + role.mypos[0] + ',' + role.mypos[1] + '|';
      if (this.info.path.indexOf(mypos) == -1 || mypos == '|0,0|') {
        let path = this.paths[Math.floor(Math.random() * this.paths.length)];
        role.goTo(this, path[0], path[1], 0);
      } else {
        role.goTo(this, role.mypos[0], role.mypos[1], 0);
      }
    },
    async roleMove(r) {
      let { roleId, animate } = r;
      if (roleId == this.$game.uid()) {
        var role = await this.getRole(roleId);
        if (!role) {
          return;
        }

        var x = role.mypos[0] * this.size;
        var y = role.mypos[1] * this.size;

        this.smallMap.x = x * this.smallMap.zoom;
        this.smallMap.y = y * this.smallMap.zoom;

        var left = x * this.sceneZoom - this.$game.width / 2;
        var top = y * this.sceneZoom - this.$game.height / 2;
        left = Math.min(this.info.width - this.$game.width, left);
        left = Math.max(0, left);
        top = Math.min(this.info.height - this.$game.height, top);
        top = Math.max(0, top);
        this.updateBigMap(left, top);
        if (this.infoBack) {
          this.$refs.scene.goTo([-left, 0, animate ? 1000 : 0]);
          this.$refs.sceneBack.goTo([-left, 0, animate ? 1000 : 0]);
        } else {
          this.$refs.scene.goTo([-left, -top, animate ? 1000 : 0]);
        }
      }
    },
    async mouse(x, y) {
      this.mouse_show = true;
      this.$refs.mouse.goTo([x, y, 0]);
      await this.$refs.mouse.playOnce();
      this.mouse_show = false;
    },
    //定时保存位置
    async wayTo(col, row) {
      let uid = this.$game.uid();
      this.role(uid, async role => {
        let timer;
        let running = true;
        if (this.$game.global.userid) {
          timer = setInterval(() => {
            if (!running) {
              clearInterval(timer);
            }

            this.$game.call('data', {
              type: 'save',
              token: {
                type: 'table',
                table: 'player',
                where: {
                  userid: this.$game.global.userid
                }
              },
              values: {
                scene: this.info.name,
                mypos: role.mypos
              }
            });
          }, 2000);
        }
        if (this.info.path.indexOf('|' + role.mypos[0] + ',' + role.mypos[1] + '|') == -1) {
          role.goTo(this, col, row, 0);
        } else {
          var paths = this.$game.find_path(role.mypos, [col, row], this.map_arr, 1);
          if (paths.length > 0) {
            if (this.$game.isMe(uid)) {
              if (this.socket) {
                this.socket.emit('sendmsg', { type: 'wayTo', roleId: uid, paths: paths });
              }
            }
            await role.wayTo(this, paths);
            running = false;
          }
        }
      });
    },
    hit(e) {
      if (!this.info.path) {
        return;
      }
      let { x, y } = e;
      if (this.infoBack) {
        x /= this.sceneZoom;
        y /= this.sceneZoom;
      }
      x -= e.tx;
      y -= e.ty;
      //左边方格数
      var col = Math.floor(x / this.size);
      //上边方格数
      var row = Math.floor(y / this.size);
      var left = col * this.size;
      var top = row * this.size;
      //是否点击在路径上
      if (this.info.path.indexOf('|' + col + ',' + row + '|') != -1) {
        this.mouse(x, y);
        this.wayTo(col, row);
      }
    }
  }
};
</script>
<style scoped>
.onez-scene {
  overflow: hidden;
}
.onez-scene-front {
}
.path {
  position: absolute;
  pointer-events: none;
  background: rgba(0, 0, 0, 0.3);
}
.way {
  background: rgba(255, 0, 0, 0.3);
}
.onez-scene-back {
  zoom: 1.1;
}
.sceneBox {
  transform-origin: 0 0;
}
.tile {
  position: absolute;
  width: 320px;
  height: 320px;
  display: block;
  transform: scale(1.001);
}
.smallMap {
  position: fixed;
  z-index: 6200103;
  background-size: 100% 100%;
}
.smallMap .border {
  position: absolute;
  left: -5px;
  top: -5px;
  z-index: 1;
  pointer-events: all !important;
}
.dot {
  transform: translate3d(-19px, -19px, 0) scale(0.5, 0.5) !important;
  position: absolute;
  display: block;
  z-index: 10;
}
</style>
